#include "head.h"
typedef struct storage_goods_info
{
	unsigned char new_goods;  //有新货物来
	unsigned char goods_type; //货物类型，用数字表示
	unsigned int goods_count; //货物数量
} storage_goods_info_ty;
//某个仓库的全部信息
typedef struct storage_info
{
	unsigned char storage_status; //仓库状态是否有入侵
	unsigned char led_status;	  //led状态
	unsigned char buzzer_status;  //蜂鸣器状态
	unsigned char fan_status;	  //风扇状态
	unsigned char seg_status;	  //隔离状态
	signed char x;
	signed char y;
	signed char z;
	float temperature;	   //温度
	float temperatureMIN;  //温度
	float temperatureMAX;  //温度
	float humidity;		   //湿度
	float humidityMIN;	   //湿度
	float humidityMAX;	   //湿度
	float illumination;	   //光照
	float illuminationMIN; //光照
	float illuminationMAX; //光照
	struct storage_goods_info goods_info;
} storage_info_ty;
//所有仓库的信息结构体
/*typedef struct env_info_clien_addr
{
	struct storage_info storage_no[STORAGE_NUM];
} env_infoenv_info_clien_addr_ty;*/
//线程池相应结构体
typedef struct work
{
	void *(*process)(void *arg); //执行任务的函数指针可以是各种函数
	void *args;					 //传递的参数
	struct work *next;			 //指向队列的下一个成员
} worker;
//线程池相应结构体
typedef struct
{
	pthread_mutex_t pool_lock; //互斥锁
	pthread_cond_t cond;	   //条件变量使线程阻塞
	worker *queuehead;		   //线程号
	int cur_queue_cont;		   //当前队列中成员个数
	pthread_t *pthread_num;
	int max_thread; //线程池中线程的个数
	int shutdown;	//线程停止标志
} pool;
pool *mypool;
//消息队列结构体从QT上接收消息队列
typedef struct msg
{
	long type1;
	long msgtype_led;
	long msgtype_buzzer;
	long msgtype_send;
	long red_off_on;
	long green_off_on;
	long blue_off_on;
	long buzzer_off_on;
	float temperatureMIN;  //温度
	float temperatureMAX;  //温度
	float humidityMIN;	   //湿度
	float humidityMAX;	   //湿度
	float illuminationMIN; //光照
	float illuminationMAX; //光照
						   //unsigned char text[QUEUE_MSG_LEN];
} msgbuf_ty;
//消息队列的长度不包括long
#define MSG_LEN sizeof(struct msg) - sizeof(long)

//创建TCP服务端用于接收ZigBee传来的数据和发送数据给M0
int createTcpSocket(short port);
void *thread_routine(void *args);
void add_work(void *(*process)(void *), void *args);
void create_poll(int num);
void destory_pool();

void *pthread_client_request(void *arg);
void *pthread_transfer(void *arg);
void *pthread_led(void *arg);
void *phtread_buzzer(void *arg);
//void *pthread_camera(void *arg);
void *pthread_analysis(void *arg);
void *pthread_refresh(void *arg);
void *pthread_sqlite(void *arg);

pthread_mutex_t mymutex;
pthread_cond_t mycond_client_request = PTHREAD_COND_INITIALIZER;
pthread_cond_t mycond_transfer = PTHREAD_COND_INITIALIZER;
pthread_cond_t mycond_led = PTHREAD_COND_INITIALIZER;
pthread_cond_t mycond_buzzer = PTHREAD_COND_INITIALIZER;
//pthread_cond_t mycond_camera = PTHREAD_COND_INITIALIZER;
pthread_cond_t mycond_analysis = PTHREAD_COND_INITIALIZER;
pthread_cond_t mycond_refresh = PTHREAD_COND_INITIALIZER;
pthread_cond_t mycond_sqlite = PTHREAD_COND_INITIALIZER;
storage_info_ty storage;
msgbuf_ty msgbuf;
sqlite3 *db;
//主函数
int main(int argc, const char *argv[])
{
	int ret;
	ret = sqlite3_open("./storage_info.db", &db);
	if (ret != 0)
	{
		printf("sqlite3_open:%s\n", sqlite3_errmsg(db));
		return -1;
	}
	pthread_cond_init(&mycond_client_request, NULL);
	pthread_cond_init(&mycond_transfer, NULL);
	pthread_cond_init(&mycond_led, NULL);
	pthread_cond_init(&mycond_buzzer, NULL);
//	pthread_cond_init(&mycond_camera, NULL);
	pthread_cond_init(&mycond_analysis, NULL);
	pthread_cond_init(&mycond_refresh, NULL);
	pthread_cond_init(&mycond_sqlite, NULL);
	pthread_mutex_init(&mymutex, NULL); //互斥锁
	int sfd = createTcpSocket(12345);
	create_poll(10);
	int clientFd;
	struct sockaddr_in clientAddr;
	int alen = sizeof(clientAddr);
	while (1)
	{
		clientFd = accept(sfd, (struct sockaddr *)&clientAddr, &alen);
		if (clientFd < 0)
		{
			perror("accept");
			return -1;
		}
	}
	//处理消息队列里请求的线程的处理函数
	add_work(pthread_client_request, (void *)&clientFd);
	//接收数据线程的处理函数
	add_work(pthread_transfer, (void *)&clientFd);
	add_work(pthread_led, NULL);
	//A53 蜂鸣器模块线程.的处理函数
	add_work(phtread_buzzer, NULL);
	/*	//摄像头模块控制线程的处理函数
	add_work(pthread_camera, NULL);*/
	//数据分析线程.的处理函数
	add_work(pthread_analysis, NULL);
	//更新共享内存里的实时数据.
	add_work(pthread_refresh, NULL);
	//数据库线程
	add_work(pthread_sqlite, NULL);
	while (1)
	{
		sleep(1);
	}
	//销毁线程池
	destory_pool();
	free(mypool);
	printf("free resource is ok.\n");
	return 0;
}

void *pthread_client_request(void *arg)
{
	int clientFd = *((int *)arg);
	key_t key;
	int msgid;
	key = ftok("./msg", 133);
	if (key == -1)
	{
		perror("ftok");
		return NULL;
	}
	//创建消息队列
	msgid = msgget(key, IPC_CREAT | 0666);
	if (msgid == -1)
	{
		perror("msgget");
		return NULL;
	}
	int rlen;
	int led_statues = ONE_HUNGER;
	int buzzer_statues = ONE_HUNGER;

	while (1)
	{
		pthread_mutex_lock(&mymutex);
		pthread_cond_wait(&mycond_client_request, &mymutex);
		//用消息队列从QT端接收信息
		rlen = msgrcv(msgid, &msgbuf, MSG_LEN, 0, IPC_NOWAIT);
		if (rlen == -1)
		{
			perror("msgrcv");
			return NULL;
		}
		/*1L为唤醒A8上的led线程，同时需要对led命令掩码进行赋值，程序规定去消息正文的第一个字节作为命令控制字；
		2L为唤醒A8上的蜂鸣器进程，同时对蜂鸣器命令掩码进行赋值；
		3L是唤醒摄像头线程进行抓拍，同时对抓拍命令掩码进行赋值，这里的抓拍命令掩码是抓拍的照片数量；
		4L是向M0发送数据，这里将发送命令掩码直接写入ZigBee串口，没有另外唤醒发送线程；
		5L根据消息正文对相应的环境参数阈值进行设置，唤醒共享内存刷新线程
		5L短信模块控制线程*/
		if (led_statues != msgbuf.msgtype_led)
		{
			if (msgbuf.msgtype_led == ON || msgbuf.msgtype_led == OFF)
			{
				//A53LED 模块线程.的处理函数
				pthread_cond_signal(&mycond_led);
				led_statues = msgbuf.msgtype_led;
			}
		}
		if (buzzer_statues != msgbuf.msgtype_buzzer)
		{
			if (msgbuf.msgtype_buzzer == ON || msgbuf.msgtype_buzzer == OFF)
			{
				//A53 蜂鸣器模块线程.的处理函数
				pthread_cond_signal(&mycond_buzzer);
				buzzer_statues = msgbuf.msgtype_buzzer;
			}
		}
		/*if (msgbuf.msgtype_camera == ON || msgbuf.msgtype_camera == OFF)
		{
			//摄像头模块控制线程的处理函数
			pthread_cond_signal(&mycond_camera);
		}*/
		//在QT图形化界面，点击一次发送给M0按钮后，msgbuf.msgtype_send会变为OFF
		if (msgbuf.msgtype_send == ON)
		{
			send(clientFd, &msgbuf, sizeof(struct storage_info), 0);
			//控制命令发送线程.的处理函数取消
			//add_work(pthread_uart_cmd, NULL);
			//发送数据给zigbee通讯
		}
		/*case 5:
			//短信模块控制线程.的处理函数
			add_work(pthread_sms, NULL);
			break;
		*/
		pthread_mutex_unlock(&mymutex);
		while (1)
		{
			sleep(1);
		}
	}
}
void *pthread_transfer(void *arg)
{
	int clientFd = *((int *)arg);
	{
		while (1)
		{
			pthread_mutex_lock(&mymutex);
			recv(clientFd, &storage, sizeof(struct storage_info), 0);
			pthread_mutex_unlock(&mymutex);
			pthread_cond_signal(&mycond_analysis);
		}
	}
	while (1)
	{
		sleep(1);
	}
}
void *pthread_led(void *arg)
{
	int fd_led;
	fd_led = open("/dev/dev-led1", O_RDWR);
	if (fd_led == -1)
	{
		perror("open /dev/led error");
		return NULL;
	}
	while (1)
	{
		pthread_mutex_lock(&mymutex);
		pthread_cond_wait(&mycond_led, &mymutex);
		if (msgbuf.msgtype_led == ON)
		{
			if (storage.temperature >= storage.temperatureMAX || storage.temperature <= storage.temperatureMIN)
			{
				if (msgbuf.red_off_on == ON)
				{
					ioctl(fd_led, RED_ON);
				}
				else if (msgbuf.red_off_on == OFF)
				{
					ioctl(fd_led, RED_OFF);
				}
				else
				{
					ioctl(fd_led, RED_ON);
				}
			}
			else if(storage.temperature > storage.temperatureMIN && storage.temperature < storage.temperatureMAX)
				{
					if (msgbuf.red_off_on == ON)
					{
						ioctl(fd_led, RED_ON);
					}
					else if (msgbuf.red_off_on == OFF)
					{
						ioctl(fd_led, RED_OFF);
					}
					else
					{
						ioctl(fd_led, RED_OFF);
					}
				}
			if (storage.humidity >= storage.humidityMAX || storage.humidity <= storage.humidityMIN)
			{
				if (msgbuf.green_off_on == ON)
				{
					ioctl(fd_led, GREEN_ON);
				}
				else if (msgbuf.green_off_on == OFF)
				{
					ioctl(fd_led, GREEN_OFF);
				}
				else
				{
					ioctl(fd_led, GREEN_ON);
				}
			}
			else if(storage.humidity > storage.humidityMIN && storage.humidity < storage.humidityMAX)
				{
					if (msgbuf.green_off_on == ON)
					{
						ioctl(fd_led, GREEN_ON);
					}
					else if (msgbuf.green_off_on == OFF)
					{
						ioctl(fd_led, GREEN_OFF);
					}
					else
					{
						ioctl(fd_led, GREEN_OFF);
					}
				}
			if (storage.illumination >= storage.illuminationMAX || storage.illumination <= storage.illuminationMIN)
			{
				if (msgbuf.blue_off_on == ON)
				{
					ioctl(fd_led, BLUE_ON);
				}
				else if (msgbuf.blue_off_on == OFF)
				{
					ioctl(fd_led, BLUE_OFF);
				}
				else
				{
					ioctl(fd_led, BLUE_ON);
				}
			}
			else if(storage.illumination > storage.illuminationMIN && storage.illumination < storage.illuminationMAX)
				{
					if (msgbuf.blue_off_on == ON)
					{
						ioctl(fd_led, BLUE_ON);
					}
					else if (msgbuf.blue_off_on == OFF)
					{
						ioctl(fd_led, BLUE_OFF);
					}
					else
					{
						ioctl(fd_led, BLUE_OFF);
					}
				}
		}
		else if (msgbuf.msgtype_led == OFF)
		{
			ioctl(fd_led, RED_OFF);
			ioctl(fd_led, GREEN_OFF);
			ioctl(fd_led, BLUE_OFF);
		}
		pthread_mutex_unlock(&mymutex);
	}
	while (1)
	{
		sleep(1);
	}
}
void *phtread_buzzer(void *arg)
{
	int fd_pwd;
	fd_pwd = open("/dev/dev-pwd1", O_RDWR);
	if (fd_pwd == -1)
	{
		perror("open /dev/pwd error");
		return NULL;
	}
	while (1)
	{
		pthread_mutex_lock(&mymutex);
		pthread_cond_wait(&mycond_buzzer, &mymutex);
		if (msgbuf.msgtype_buzzer == ON)
		{
			if (storage.seg_status == STORAGE_STATUS_ON)
			{
				if (msgbuf.buzzer_off_on == ON)
				{
					ioctl(fd_pwd, PWM_ON);
				}
				else if (msgbuf.buzzer_off_on == OFF)
				{
					ioctl(fd_pwd, PWM_OFF);
				}
				else
				{
					ioctl(fd_pwd, PWM_ON);
				}
			}
		}
		else if (msgbuf.msgtype_buzzer == OFF)
		{
			ioctl(fd_pwd, PWM_OFF);
		}
		pthread_mutex_unlock(&mymutex);
	}
	while (1)
	{
		sleep(1);
	}
}
/*
	void *pthread_camera(void *arg)
	{
		pthread_mutex_lock(&mymutex);
		pthread_cond_wait(&mycond_camera, &mymutex);
		pthread_mutex_unlock(&mymutex);
		while (1)
		{
			sleep(1);
		}
	}*/
void *pthread_analysis(void *arg)
{
	while (1)
	{
		pthread_mutex_lock(&mymutex);
		pthread_cond_wait(&mycond_analysis, &mymutex);
		if (storage.goods_info.new_goods == 'y')
		{
			pthread_cond_signal(&mycond_sqlite);
		}
		pthread_cond_signal(&mycond_refresh);
		pthread_cond_signal(&mycond_client_request);
		pthread_mutex_unlock(&mymutex);
	}
	while (1)
	{
		sleep(1);
	}
}
//共享内存发送
void *pthread_refresh(void *arg)
{
	storage_info_ty *storage_refresh;
	key_t key;
	int shmid;
	key = ftok(".", 123);
	if (key == -1)
	{
		perror("ftok");
		return NULL;
	}
	shmid = shmget(key, 256, IPC_CREAT | 0666);
	if (shmid == -1)
	{
		perror("shmget");
		return NULL;
	}
	while (1)
	{
		pthread_mutex_lock(&mymutex);
		pthread_cond_wait(&mycond_refresh, &mymutex);
		storage_refresh = shmat(shmid, NULL, 0);
		memcpy(storage_refresh, &storage, sizeof(storage_info_ty));
		//shmdt(storage_refresh);
		pthread_mutex_unlock(&mymutex);
	}
	while (1)
	{
		sleep(1);
	}
}
void *pthread_sqlite(void *arg)
{
	char * errmsg;
	while (1)
	{
		pthread_mutex_lock(&mymutex);
		pthread_cond_wait(&mycond_sqlite, &mymutex);
		char storage_info[DATALEN] = {0};
		sprintf(storage_info, "insert into storage_info values ('%c','%c','%c','%c','%c','%c','%c','%c','%f','%f', '%f', '%f', '%f', '%f', '%f', '%f', '%f','%c','%u');",
				storage.storage_status, storage.led_status, storage.buzzer_status, storage.fan_status, storage.seg_status,
				storage.x, storage.y, storage.z, storage.temperature, storage.temperatureMAX, storage.temperatureMIN,
				storage.humidity, storage.humidityMAX, storage.humidityMIN, storage.illumination, storage.illuminationMAX,
				storage.illuminationMIN, storage.goods_info.goods_type, storage.goods_info.goods_count);
		if (sqlite3_exec(db, storage_info, NULL, NULL, &errmsg) != SQLITE_OK)
		{
			printf("%s.\n", errmsg);
			printf("insert storage_info failed.\n");
		}
		else
		{
			printf("insert storage_info success.\n");
		}
		pthread_mutex_unlock(&mymutex);
	}
	while (1)
	{
		sleep(1);
	}
}
void *thread_routine(void *args)
{
	pthread_t *tid = (pthread_t *)args;
	printf("start thread id = %ld.\n", *tid);
	while (1)
	{
		pthread_mutex_lock(&mypool->pool_lock);
		if (mypool->cur_queue_cont == 0 && !mypool->shutdown)
		{
			pthread_cond_wait(&mypool->cond, &mypool->pool_lock);
		}
		if (mypool->shutdown)
		{
			pthread_mutex_unlock(&mypool->pool_lock);
			pthread_exit(NULL);
		}
		mypool->cur_queue_cont--;
		worker *work = mypool->queuehead;
		mypool->queuehead = work->next;
		pthread_mutex_unlock(&mypool->pool_lock);
		work->process((void *)work->args);
	}
}
void add_work(void *(*process)(void *), void *args)
{
	worker *work = (worker *)malloc(sizeof(worker));
	work->process = process;				//执行任务的函数指针
	work->args = args;						//传递的参数
	work->next = NULL;						//指向队列的下一个成员
	pthread_mutex_lock(&mypool->pool_lock); //互斥锁
	worker *pwork = mypool->queuehead;		//队列头
	if (pwork != NULL)
	{
		while (pwork->next != NULL)
			pwork = pwork->next;
		pwork->next = work;
	}
	else
	{
		mypool->queuehead = work;
	}
	mypool->cur_queue_cont++; //当前队列中成员个数
	pthread_mutex_unlock(&mypool->pool_lock);
	pthread_cond_signal(&mypool->cond);
}
void create_poll(int num)
{
	int i, ret;
	mypool = (pool *)malloc(sizeof(*mypool));
	if (mypool == NULL)
	{
		printf("malloc pool memory is fail.\n");
		return;
	}
	pthread_mutex_init(&mypool->pool_lock, NULL);
	pthread_cond_init(&mypool->cond, NULL);
	mypool->queuehead = NULL;
	mypool->shutdown = 0;
	mypool->max_thread = num;
	mypool->pthread_num = (pthread_t *)malloc(num * sizeof(pthread_t));
	for (i = 0; i < num; i++)
	{
		ret = pthread_create(&(mypool->pthread_num[i]), NULL, thread_routine, (void *)&(mypool->pthread_num[i]));
		if (ret != 0)
		{
			printf("create thread is fail.\n");
		}
	}
}
//销毁线程池函数
void destory_pool()
{
	int i;
	mypool->shutdown = 1;
	pthread_cond_broadcast(&mypool->cond);
	for (i = 0; i < mypool->max_thread; i++)
	{
		pthread_join(mypool->pthread_num[i], NULL);
	}
	free(mypool->pthread_num);

	worker *tmp;
	while (mypool->queuehead)
	{
		tmp = mypool->queuehead;
		mypool->queuehead = mypool->queuehead->next;
		free(tmp);
	}
	pthread_mutex_destroy(&mypool->pool_lock);
	pthread_cond_destroy(&mypool->cond);
}
int createTcpSocket(short port)
{
	int sfd;
	struct sockaddr_in serverAddr;
	int alen = sizeof(serverAddr);
	sfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sfd < 0)
	{
		perror("socket");
		return -1;
	}
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_port = htons(port); //0x3930;
	serverAddr.sin_addr.s_addr = 0;	   //inet_addr("192.168.1.8");//0xC0A80108;
	int ret;
	ret = bind(sfd, (struct sockaddr *)&serverAddr, alen);
	if (ret < 0)
	{
		perror("bind");
		return -1;
	}

	ret = listen(sfd, 5);
	if (ret < 0)
	{
		perror("listen");
		return -1;
	}
	return sfd;
}